package com.jxb.service;

import org.apache.lucene.search.join.ScoreMode;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.MatchQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.AggregatorFactories;
import org.elasticsearch.search.aggregations.bucket.terms.TermsAggregationBuilder;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.sort.*;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import javax.json.Json;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

import com.alibaba.fastjson.JSON;

@Component
public class Service {

    @Resource
    private RestHighLevelClient restHighLevelClient;

    /**
     * GET /product_db/_search
     * {
     *   "query": {
     *     "bool": {
     *       "must": [
     *         {
     *           "multi_match": {
     *             "query": "朵唯手机",
     *             "fields": [
     *               "name",
     *               "keywords",
     *               "subTitle"
     *             ]
     *           }
     *         }
     *       ],
     *       "filter": [
     *         {
     *           "range": {
     *             "price": {
     *               "gte": 2000,
     *               "lte": 10000
     *             }
     *           }
     *         },
     *         {
     *           "range": {
     *             "putawayDate": {
     *               "gte": "2021-05-02",
     *               "lte": "2021-06-03"
     *             }
     *           }
     *         },
     *         {
     *           "term": {
     *             "categoryId": "19"
     *           }
     *         },
     *         {
     *           "nested": {
     *             "path": "attrs",
     *             "query": {
     *               "bool": {
     *                 "must": [
     *                   {
     *                     "match": {
     *                       "attrs.attrName": "容量"
     *                     }
     *                   },
     *                   {
     *                     "match": {
     *                       "attrs.attrValue": "128G"
     *                     }
     *                   }
     *                 ]
     *               }
     *             }
     *           }
     *         }
     *       ]
     *     }
     *   },
     *   "aggs": {
     *     "brand_agg": {
     *       "terms": {
     *         "field": "brandId"
     *       },
     *       "aggs": {
     *         "brand_name_agg": {
     *           "terms": {
     *             "field": "brandName"
     *           }
     *         },
     *         "brand_img_agg":{
     *           "terms": {
     *             "field": "brandImg"
     *           }
     *         }
     *       }
     *     }
     *   },
     *   "sort": [
     *     {
     *       "salecount": {
     *         "order": "desc"
     *       }
     *     },
     *     {
     *       "price": {
     *         "order": "desc"
     *       }
     *     },
     *     {
     *       "putawayDate": {
     *         "order": "desc"
     *       }
     *     }
     *   ],
     *   "from": 0,
     *   "size": 10,
     *   "highlight": {
     *     "post_tags": ["</span>"],
     *     "pre_tags": ["<span style='color:red'>"],
     *     "fields": {
     *       "*":{}
     *     }
     *   }
     * }
     * @param reqDO
     * @return
     */
    public Object search(ReqDO reqDO) {

        //构建检索对象
        SearchRequest searchRequest = startBuildDSL(reqDO);
        //进行检索操作
        SearchResponse search = null;
        try {
            search = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return search;
    }

    private SearchRequest startBuildDSL(ReqDO reqDO) {

        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();

        //1:封装bool请求
        BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder();
        //封装关键字
        if (!StringUtils.isEmpty(reqDO.getKeywords())) {
            boolQueryBuilder.must(QueryBuilders.multiMatchQuery(reqDO.getKeywords(),"name","keywords","subTitle"));
        }

        //2：封装filter
        if(reqDO.getPriceMin() != null && reqDO.getPriceMax() != null) {
            boolQueryBuilder.filter(QueryBuilders.rangeQuery("price").lte(reqDO.getPriceMax()).gte(reqDO.getPriceMin()));
        }
        if (!StringUtils.isEmpty(reqDO.getPutawayDateMax()) && !StringUtils.isEmpty(reqDO.getPutawayDateMin())) {
            boolQueryBuilder.filter(QueryBuilders.rangeQuery("putawayDate").lte(reqDO.getPutawayDateMax()).gte(reqDO.getPutawayDateMin()));
        }
        if (reqDO.getCategoryId() != null) {
            boolQueryBuilder.filter(QueryBuilders.termQuery("categoryId",reqDO.getCategoryId()));
        }
        if (!StringUtils.isEmpty(reqDO.getAttrName()) && !StringUtils.isEmpty(reqDO.getAttrValue()) ) {
            List<MatchQueryBuilder> builders = new ArrayList<>();
            builders.add(QueryBuilders.matchQuery("attrs.attrName", reqDO.getAttrName()));
            builders.add(QueryBuilders.matchQuery("attrs.attrValue",reqDO.getAttrValue()));
            BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
            queryBuilder.must().addAll(builders);
            boolQueryBuilder.filter(
                    QueryBuilders.nestedQuery("attrs",queryBuilder
                            , ScoreMode.None));
        }
        searchSourceBuilder.query(boolQueryBuilder);

        //3：封装聚合
        TermsAggregationBuilder brandAggs = AggregationBuilders.terms("brand_agg");
        brandAggs.field("brandId").size(50);
        brandAggs.subAggregation(AggregationBuilders.terms("brand_name_agg").field("brandName").size(1));
        brandAggs.subAggregation(AggregationBuilders.terms("brand_img_agg").field("brandImg").size(1));
        searchSourceBuilder.aggregation(brandAggs);

        //4：封装排序
        FieldSortBuilder saleSortBuilder = SortBuilders.fieldSort("salecount").order(SortOrder.DESC);
        FieldSortBuilder priceSortBuilder = SortBuilders.fieldSort("price").order(SortOrder.DESC);
        FieldSortBuilder putawayDateBuilder = SortBuilders.fieldSort("putawayDate").order(SortOrder.DESC);
        searchSourceBuilder.sort(saleSortBuilder);
        searchSourceBuilder.sort(priceSortBuilder);
        searchSourceBuilder.sort(putawayDateBuilder);

        //5：封装分页
        searchSourceBuilder.from(0);
        searchSourceBuilder.size(10);

        //6：封装高亮
        HighlightBuilder highlightBuilder = new HighlightBuilder();
        highlightBuilder.postTags("</span>");
        highlightBuilder.preTags("<span style='color:red'>");
        highlightBuilder.field("name").field("keywords").field("subTitle");
        searchSourceBuilder.highlighter(highlightBuilder);

        //7:返回
        return new SearchRequest(new String[]{"product_db"},searchSourceBuilder);
    }

}
